#ifndef __GZ_INTERFACE_ACTION_CLIENT_H__
#define __GZ_INTERFACE_ACTION_CLIENT_H__

#include <string>
#include <functional>
#include <memory>

namespace Gazella {

//callbacks typedef
typedef std::function<void(bool, const std::string&)> action_goal_response_callback_t;
typedef std::function<void(bool, const std::string&)> action_cancel_response_callback_t;

typedef std::function<void(const std::string&)> action_feedback_callback_t;
typedef std::function<void(const std::string&)> action_result_callback_t;

class GzActionClient {
public:
    GzActionClient();
    ~GzActionClient();

    void reset();

    //async action goal
    int action_goal (
        const std::string& service_name,
        const std::string& if_name,
        const std::string& request_payload,

        action_goal_response_callback_t goal_response_callback,
        action_feedback_callback_t      feedback_callback,
        action_result_callback_t        result_callback,
        
        uint32_t timeout = 3,

        //if loadbalance == false
        //set host_ip and pod_ip uniquely specify a service
        bool loadbalance = true,
        const std::string& service_uuid = "",

        //traceid to follow call route 
        const std::string& traceid = "",
        //call transmission priority
        uint32_t priority = 0
    );

    //sync action goal
    std::string action_goal (
        const std::string& service_name,
        const std::string& if_name,
        const std::string& request_payload,

        action_feedback_callback_t feedback_callback,
        action_result_callback_t   result_callback,

        uint32_t timeout = 3,

        //if loadbalance == false
        //set host_ip and pod_ip uniquely specify a service
        bool loadbalance = true,
        const std::string& service_uuid = "",

        //traceid to follow call route 
        const std::string& traceid = "",
        //call transmission priority
        uint32_t priority = 0
    );

    //async action cancel
    int action_cancel (
        const std::string& service_name,
        const std::string& if_name,
        const std::string& request_payload,

        action_cancel_response_callback_t cancel_response_callback,

        uint32_t timeout = 3,

        //if loadbalance == false
        //set host_ip and pod_ip uniquely specify a service
        bool loadbalance = true,
        const std::string& service_uuid = "",

        //traceid to follow call route 
        const std::string& traceid = "",
        //call transmission priority
        uint32_t priority = 0
    );

    //sync action cancel
    std::string action_cancel (
        const std::string& service_name,
        const std::string& if_name,
        const std::string& request_payload,

        uint32_t timeout = 3,

        //if loadbalance == false
        //set host_ip and pod_ip uniquely specify a service
        bool loadbalance = true,
        const std::string& service_uuid = "",

        //traceid to follow call route 
        const std::string& traceid = "",
        //call transmission priority
        uint32_t priority = 0
    );

private:
    void __mqtt_subscribe_callback(const std::string& topic, uint8_t qos, const std::string& payload);

private:
    std::string m_action_session;
    std::string m_action_topic;

    action_feedback_callback_t m_feedback_callback;
    action_result_callback_t   m_result_callback;
};

} //namespace Gazella

#endif